package first.endtoend

import first.endtoend.messages.MessageCode
import org.springframework.dao.DataIntegrityViolationException

import java.text.SimpleDateFormat

class FamilyController
{

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
    def parseCSVBeneficiaryService
    def parseXMLBeneficiaryService
    def myList
    def filterPaneService
    def springSecurityService
    def sendNotificationService

    Role roleAgent = Role.findByAuthority('ROLE_AGENT')
    Role roleAdmin = Role.findByAuthority('ROLE_ADMIN')
    Agent agentInstance
    Admin adminInstance
    User userInstance


    def index()
    {
        redirect(action: "list", params: params)
    }

    def list(Integer max)
    {
        def families = new ArrayList<Family>()
        params.max = Math.min(max ?: 10, 100)
        userInstance = springSecurityService.currentUser
        if (userInstance.authorities.contains(roleAgent))
        {
            agentInstance = (Agent) userInstance
            getFamiliesByAgent(agentInstance)
        } else if (userInstance.authorities.contains(roleAdmin))
        {
            adminInstance = (Admin) userInstance
            getFamiliesByAdminLevel(adminInstance)
        } else
        {
            [familyInstanceList: Family.list(params), familyInstanceTotal: Family.count()]
        }

    }

    def create()
    {
        [familyInstance: new Family(params)]
    }

    def save()
    {
        println(params)

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd")
        Date startDate = sdf.parse(params.startDate)
        Date endDate = sdf.parse(params.endDate)

        def familyInstance = new Family(params)
        def localityInstance = Locality.get(Long.valueOf(params.localitySelect))
        def Portfolio portfolioInstance
        println("--->" + localityInstance)
        Address adress
        if (localityInstance)
        {
            adress = new Address(numStreet: params.numStreet, nameStreet: params.nameStreet, zipCode: params.zipCode, locality: localityInstance, localityName: localityInstance.name)
        } else
        {
            flash.message = message(code: 'default.not.found.locality.message')
            redirect(action: "create")
            return
        }
        if (adress != null)
        {
            adress.save()
            familyInstance.address = adress

        }


        if (!familyInstance.save(flush: true))
        {
            render(view: "create", model: [familyInstance: familyInstance, addressInstance: adress, localityInstance: localityInstance])
            return
        }

        if (familyInstance != null)
        {
            portfolioInstance = new Portfolio(startDate: startDate, endDate: endDate, dateCreated: startDate, lastUpdated: startDate, family: familyInstance)
            portfolioInstance.save(flush: true)
        }

        if (params.fps)
        {
            println("here fps :" + params.fps)
            Agent agentInstance
            FairPricesShop fpsInstance = FairPricesShop.findById(Long.valueOf(params.fps.id))
            if (fpsInstance)
            {
                agentInstance = Agent.findByFps(fpsInstance)
            }

            Notification notificationInstance
            if (agentInstance && familyInstance.rationCard != null)
            {
                notificationInstance = new Notification(agent: agentInstance, idModel: familyInstance.id, code: MessageCode.FAMILY_ADD.value(), modelName: Family.getSimpleName(), description: message(code: 'family.add.notification.message', default: "There is a new Family added") + familyInstance.familyName).save()
            }
        }



        flash.message = message(code: 'default.created.message', args: [message(code: 'family.label', default: 'Family'), familyInstance.id])
        redirect(action: "create", controller: "beneficiary", id: familyInstance.id)


    }

    def show(Long id, Long idRationCard)
    {

        def familyInstance = Family.get(id)
        if (!familyInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'family.label', default: 'Family'), id])
            redirect(action: "list")
            return
        }
        if (idRationCard != null)
        {
            RationCard rationCardInstance = RationCard.findById(idRationCard)
            if (rationCardInstance)
            {
                familyInstance.rationCard = rationCardInstance
            }
        } else
        {
            //no rationCard assigned to family
        }


        [familyInstance: familyInstance]
    }

    def edit(Long id)
    {
        def familyInstance = Family.get(id)

        if (!familyInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'family.label', default: 'Family'), id])
            redirect(action: "list")
            return
        }

        [familyInstance: familyInstance, addressInstance: familyInstance.address, localityInstance: familyInstance.address.locality, portfolioInstance: familyInstance.portfolio]
    }

    def update(Long id, Long version)
    {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
        Date startDate = sdf.parse(params.startDate)
        Date endDate = sdf.parse(params.endDate)
        Date lastUpdated = new Date()

        def familyInstance = Family.get(id)
        println("HEYYY" + params)
        def localityInstance = Locality.findById(Long.valueOf(params.localitySelect))
        println("--->" + localityInstance)
        //Address adress= new Address(numStreet: params.num, zipCode:params.zipCode, locality:localityInstance, localityName:localityInstance.name)
        Address adress = familyInstance.address
        Portfolio portfolioInstance = familyInstance.portfolio
        if (adress)
        {
            adress.numStreet = params.numStreet
            adress.nameStreet = params.nameStreet
            adress.zipCode = params.zipCode
            adress.locality = localityInstance
            adress.localityName = localityInstance.name

            adress.save(flush: true)

        } else
        {
            println("here address doesn't exist!")
        }
        if (adress != null)
        {
            familyInstance.address = adress
        } else
        {
            println("adress null")
        }
        if (!familyInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'family.label', default: 'Family'), id])
            redirect(action: "list")
            return
        }

        if (portfolioInstance)
        {
            portfolioInstance.startDate = startDate
            portfolioInstance.endDate = endDate
            portfolioInstance.lastUpdated = lastUpdated
        }

        if (version != null)
        {
            if (familyInstance.version > version)
            {
                familyInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                        [message(code: 'family.label', default: 'Family')] as Object[],
                        "Another user has updated this Family while you were editing")
                render(view: "edit", model: [familyInstance: familyInstance])
                return
            }
        }

        familyInstance.properties = params

        if (!familyInstance.save(flush: true))
        {
            render(view: "edit", model: [familyInstance: familyInstance])
            return
        }

        adress.family = familyInstance
        FairPricesShop fpsInstance = familyInstance.fps
        if (fpsInstance)
        {
            agentInstance = Agent.findByFps(fpsInstance)

        }

        Notification notificationInstance
        if (agentInstance && familyInstance.rationCard != null)
        {
            notificationInstance = new Notification(agent: agentInstance, idModel: familyInstance.id, code: MessageCode.FAMILY_UPDATE.value(), modelName: Family.getSimpleName(), description: message(code: 'family.update.notification.message' + familyInstance.familyName, default: "There is an update of a Family")).save()
        } else
        {

        }

        redirect(action: "show", id: familyInstance.id)

        flash.message = message(code: 'default.updated.message', args: [message(code: 'family.label', default: 'Family'), familyInstance.id])

    }

    def delete(Long id)
    {
        def familyInstance = Family.get(id)
        if (!familyInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'family.label', default: 'Family'), id])
            redirect(action: "list")
            return
        }

        try
        {
            //Address adress=familyInstance.address
            /*familyInstance.beneficiaries.each {
                it.family.delete()
            }*/
            familyInstance.delete()

            /*  if(adress){
                  if(adress.family){
                      adress.family.delete()
                     // adress.save()
                  } else{

                  }

              }*/
            flash.message = message(code: 'default.deleted.message', args: [message(code: 'family.label', default: 'Family'), id])
            Agent agentInstance
            FairPricesShop fpsInstance = familyInstance.fps
            if (fpsInstance)
            {
                agentInstance = Agent.findByFps(fpsInstance)

            }

            Notification notificationInstance
            if (agentInstance)
            {

                notificationInstance = new Notification(agent: agentInstance, idModel: familyInstance.id, code: MessageCode.FAMILY_DELETE.value(), modelName: Family.getSimpleName(), description: message(code: 'family.delete.notification.message' + familyInstance.familyName, default: "There is a Family deleted ")).save()
            } else
            {
                //no notif to save
            }
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e)
        {
            flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'family.label', default: 'Family'), id])
            // redirect(action: "show", id: id)
        }


    }

    /*
    @author: Olfa : this method renders view import to choose one file
    see doc standards for this file
     */
    def importFile = {
        render(view: "import")
    }

    /*
   @author: Olfa : this method renders an intermediate view before importing all beneficiaries data
    */

    def preview()
    {
        println(params)

        myList = new ArrayList<Family>()
        def ufile = UFile.get(params.ufileId)
        println("the extension of file iiis " + ufile.getExtension())
        if (ufile.getExtension().equals("csv"))
        {
            myList = parseCSVBeneficiaryService.parseBeneficiaries(ufile.path, false)
            println("HERE CSV")
        } else if (ufile.getExtension().equals("xml"))
        {
            myList = parseXMLBeneficiaryService.parseMethod(ufile.path)
            println("HERE XML")
        }
        session["myList"] = myList

        [familyInstanceList: myList, familyInstanceTotal: myList ? myList.size() : 0]

    }

    /*
  @author: Olfa : this method validate importing data and save all beneficiaries and their adresses in database
   */

    def validate()
    {
        myList = session["myList"] as List<Family>
        def allFamilies = Family.findAll()
        println("**** all families to add" + myList)
        Family family1
        if (myList)
        {


            myList.each { family ->

                if (family != null)
                {
                    family.address.save()
                    family.save(flush: true)
                    println("** beneficiaries of this family" + family.beneficiaries.toString())
                    if (family.beneficiaries)
                    {
                        family.beneficiaries.each { benef ->
                            println("benef to add here" + benef)

                            if (family.save(flush: true))
                            {
                                println("benef to save :" + benef)
                                benef.family = family
                                benef.save()
                            } else
                            {
                                println("IN ELSE benef to save" + benef)
                            }
                        }

                    }

                } else
                {

                }

            }


        } else
        {
            println("LIST NULL!!")
        }

        session["myList"] = null
        redirect(action: "list", params: params)


    }

/*
@author: Olfa : this method shows error page if there is a problem with the import
*/

    def importFailed()
    {
        println(params)
        flash.message = message(code: 'default.fail.import.message')
        render(view: "import")
    }

/*
@author: Olfa : this method filters families, using filterPane plugin
filtering by name and telephone
*/
    def filter = {
        if (!params.max) params.max = 10
        render(view: 'list',
                model: [familyInstanceList : filterPaneService.filter(params, Family),
                        familyInstanceTotal: filterPaneService.count(params, Family),
                        filterParams       : org.grails.plugin.filterpane.FilterPaneUtils.extractFilterParams(params),
                        params             : params])
    }

/*
this method renders families related to one shop managed by anAgent
 */

    def getFamiliesByAgent(Agent anAgent)
    {
        def families = new ArrayList<Family>()
        if (anAgent.fps)
        {  //if agent is affected to a FairPriceShop
            families = Family.findAllByFps(anAgent.fps)

        } else
        {
            //no families for this agent
        }

        [familyInstanceList: families, familyInstanceTotal: families.size()]
    }

/*
@author : Olfa
this method returns all localities and their children by aLevel
*/

    private def getAllLocalitiesChildrenByAdmin(Admin anAdmin, def aLocalitiesByAdmin)
    {


        def allLocalities = new ArrayList<Locality>()


        aLocalitiesByAdmin.each {
            if (it.children)
            {
                allLocalities.add(it)
                getAllLocalitiesChildrenByAdmin(anAdmin, it.children)
            } else
            {
                allLocalities.add(it)
            }
        }
        return allLocalities
    }
/*
this method renders families in all villages managed by anAdmin
*/

    def getFamiliesByAdminLevel(Admin anAdmin)
    {
        println(params)
        def families = new ArrayList<Family>()
        Address addressInstance
        Family familyInstance
        Locality localityInstance

        def localitiesManagerByAdmin = new ArrayList<LocalityManager>()
        def localitiesByAdmin = new ArrayList<Locality>()
        localitiesManagerByAdmin = LocalityManager.findAllByManager(anAdmin)
        localitiesManagerByAdmin.each {
            localitiesByAdmin.add(it.locality)
        }

        def addressList = new ArrayList<Address>()
        def allLocalities = getAllLocalitiesChildrenByAdmin(anAdmin, localitiesByAdmin)
        println("-->ALL LOCALITIES" + allLocalities)


        allLocalities.each {
            addressList = Address.executeQuery("select distinct a from Address a where a.locality.id=?", it.id)
            if (addressList)
            {
                println("****" + addressList)
                addressList.each {

                    familyInstance = Family.findByAddress(it)
                    if (familyInstance)
                    {
                        families.add(familyInstance)

                    } else
                    {

                    }
                }
            } else
            {
                //no address found
            }

        }

        [familyInstanceList: families, familyInstanceTotal: families.size()]
    }

    def dashboard()
    {
        def familyInstance = new Family(params)
        render(view: "dashboard", model: [familyInstance: familyInstance])
    }


    def deleteProduct =
            {
                println "Delete Product"
                PortfolioDetail pfd = PortfolioDetail.findById(params.idPfd)
                pfd.delete()
                [portfolioInstance: pfd.portfolio, familyInstance: pfd.portfolio.family]

            }

    def modifyProduct =
            {
                println "Modify Product"
                PortfolioDetail pfd = PortfolioDetail.findById(params.idPfd)
                pfd.quantity = Float.parseFloat(params.quantity)
                pfd.save(flush: true)
                [portfolioInstance: pfd.portfolio, familyInstance: pfd.portfolio.family]
            }

}
